import cn.hutool.core.util.HashUtil;

import java.util.concurrent.atomic.AtomicLong;
  
public class DistributedIdGenerator {  
  
    // 开始时间戳（毫秒级），可以根据需要调整  
    private final long twepoch = 1288834974657L;  
  
    // 机器id所占的位数  
    private final long workerIdBits = 5L;  
    // 数据标识id所占的位数  
    private final long datacenterIdBits = 5L;  
    // 支持的最大机器id，结果是31  
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);  
    // 支持的最大数据标识id，结果是31  
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);  
  
    // 序列在id中占的位数  
    private final long sequenceBits = 12L;  
  
    // 机器ID向左移12位  
    private final long workerIdShift = sequenceBits;  
    // 数据标识id向左移17位(12+5)  
    private final long datacenterIdShift = sequenceBits + workerIdBits;  
    // 时间截向左移22位(5+5+12)  
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;  
  
    // 生成序列的掩码，这里为4095  
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);  
  
    // 上一次生成ID的时间截  
    private long lastTimestamp = -1L;  
  
    // 序列号  
    private long sequence = 0L;  
  
    // 机器ID  
    private final long workerId;  
    // 数据中心ID  
    private final long datacenterId;  
  
    public DistributedIdGenerator(long workerId, long datacenterId) {  
        if (workerId > maxWorkerId || workerId < 0) {  
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));  
        }  
        if (datacenterId > maxDatacenterId || datacenterId < 0) {  
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));  
        }  
        this.workerId = workerId;  
        this.datacenterId = datacenterId;  
    }  
  
    public synchronized long nextId() {  
        long timestamp = timeGen();  
  
        // 如果当前时间小于上一次ID生成的时间戳，说明系统时钟回拨过  
        if (timestamp < lastTimestamp) {  
            throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));  
        }  
  
        // 如果是同一时间生成的，则进行毫秒内序列  
        if (lastTimestamp == timestamp) {  
            sequence = (sequence + 1) & sequenceMask;  
            if (sequence == 0) {  
                // 毫秒内序列溢出  
                timestamp = tilNextMillis(lastTimestamp);  
            }  
        } else {  
            // 时间戳改变，毫秒内序列重置  
            sequence = 0L;  
        }  
  
        // 上次生成ID的时间截  
        lastTimestamp = timestamp;  
  
        // 移位并通过或运算拼到一起组成64位的ID  
        return ((timestamp - twepoch) << timestampLeftShift) |  
                (datacenterId << datacenterIdShift) |  
                (workerId << workerIdShift) |  
                sequence;  
    }  
  
    protected long tilNextMillis(long lastTimestamp) {  
        long timestamp = timeGen();  
        while (timestamp <= lastTimestamp) {  
            timestamp = timeGen();  
        }  
        return timestamp;  
    }  
  
    protected long timeGen() {  
        return System.currentTimeMillis();  
    }

    public static void main(String[] args) {
        DistributedIdGenerator a = new DistributedIdGenerator(1, 1);
        for (int i = 0; i < 4096; i++) {
            long gid = (a.nextId());
            System.out.println(gid % 100000000000000L);
        }

    }
  
    }